package com.xcity.game.vip;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.db.entity.Player;
import com.xcity.game.common.Cause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.event.GameEvents;
import com.xcity.game.shop.DiscountGoods;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.push.SyncPush;
import com.xcity.pomelo.push.sync.IntSync;
import com.xcity.pomelo.push.sync.StringSync;
import com.xcity.pomelo.request.VipBuyRequest;
import com.xcity.pomelo.request.VipListRequest;
import com.xcity.pomelo.response.HintResponse;
import com.xcity.pomelo.response.Response;
import com.xcity.pomelo.response.VipListResponse;

import naga.x.App;
import naga.x.event.Event;
import naga.x.event.EventListener;
import naga.x.game.template.TemplateService;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.Service;
import naga.x.service.ServiceException;
import naga.x.util.StringUtils;

@OPHandler
public class VipService implements Service, EventListener {

	protected List<VipTemplate> templates/*所有*/, vipTemplates/*vip>0*/;
	protected static int VIP_MAX_LEVEL;
	protected static final Logger LOG = LoggerFactory.getLogger(VipService.class);
	protected List<List<Integer>> vipSweepCountList;
	
	@Override
	public void startup() throws ServiceException {
		templates = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(VipTemplate.class);
		vipTemplates = templates.subList(1, templates.size());
		VIP_MAX_LEVEL = templates.get(templates.size() - 1).getLevel();
		App.getApp().getEventManager().register(this);
		
		vipSweepCountList = new ArrayList<List<Integer>>();
		Set<Integer> listset = new HashSet<Integer>();
		for(int i = 0; i < templates.size(); i++){
			VipTemplate temp = templates.get(i);
			int count = temp.getSweepCount();
			if(count > 0){
				listset.add(count);
			}
			List<Integer> list = new ArrayList<>();
			list.addAll(listset);
			vipSweepCountList.add(list);
		}
	}

	@Override
	public void shutdown() throws ServiceException {
	}

	@Override
	public String getId() {
		return getClass().getName();
	}

	@Override
	public int[] getEventTypes() {
		return new int[] { GameEvents.EVENT_RECHARGE, GameEvents.EVENT_RECHARGE_OFFLINE };
	}

	@Override
	public void handleEvent(Event event) {
		Player player = event.getParameter(0);
		int money = event.getParameter(1);
		onRecharge(player, money);
	}
	
	protected void onRecharge(Player player, int money) {
		int total = player.poolAdd(PlayerPool.PROPERTY_RECHARGE_TOTAL, money);
		if (player.getVipLvl() >= VIP_MAX_LEVEL) {
			return;
		}
		VipTemplate vip = moneyOf(total);
		int oldLvl = player.getVipLvl();
		if (oldLvl < vip.getLevel()) {
			player.setVipLvl(vip.getLevel());
			if (player.isOnline()) {
				player.send(new IntSync(SyncPush.SYNC_VIP, player.getVipLvl()));
			}
			if (StringUtils.isNotEmpty(vip.getHeadIcon())) {
				if (player.isOnline()) {
					player.send(new StringSync(SyncPush.SYNC_ICON, vip.getHeadIcon()));
				}
			}
			App.getApp().getEventManager().addEvent(GameEvents.EVENT_VIP_CHANGED, player, oldLvl);
			LOG.info("[VIP LEVEL CHANGE]ID[{}]OLD[{}]NEW[{}]RECHARGE[{}]", player.getId(), oldLvl, player.getVipLvl(), total);
		}
	}
	
	public VipTemplate moneyOf(int money) {
		List<VipTemplate> list = templates;
		int start = 0, end = list.size() - 1;
		VipTemplate found = list.get(0);
		while (start <= end) {
			int mid = (start + end) >> 1;
			VipTemplate t = list.get(mid);
			if (money >= t.getRechargeMoney()) {
				start = mid + 1;
				found = t;
			} else {
				end = mid - 1;
			}
		}
		return found;
	}
	
	public VipTemplate get(int level) {
		return level >= 0 && level < templates.size() ? templates.get(level) : null;
	}
	
	public List<Integer> getSweepCountList(int vipLvl){
		if(vipLvl > -1 && vipLvl < vipSweepCountList.size()){
			return vipSweepCountList.get(vipLvl);
		}
		return Collections.emptyList();
	}

	@PomeloOP(PomeloRoute.VIP_LIST)
	protected void requestVipList(Session session, VipListRequest req) {
		Player player = session.getClient();
		int nextLvl = player.getVipLvl() + 1;
		VipTemplate next = get(nextLvl);
		int needMoneyToNextLvl = next != null ? next.getRechargeMoney() - player.getPool().getIntValue(PlayerPool.PROPERTY_RECHARGE_TOTAL) : 0;
		session.send(new VipListResponse(req.getSerial(), player, needMoneyToNextLvl > 0 ? needMoneyToNextLvl : 0, vipTemplates));
	}
	
	@PomeloOP(PomeloRoute.VIP_BUY)
	protected void requestVipBuy(Session session, VipBuyRequest req) {
		Player player = session.getClient();
		int level = req.getLevel();
		VipTemplate template;
		if (player.getVipLvl() < 1 || level < 1 || level > player.getLevel() || (template = get(level)) == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.VIP_BUY_GIFT_WHEN_LEVEL_ZERO));
			return;
		}
		DiscountGoods goods = template.getGift();
		if (goods == null || goods.getTemplate() == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.VIP_HAS_NO_GIFT));
			return;
		}
		int n = player.getPool().getIntValue(PlayerPool.PROPERTY_VIP_BUY_MARK);
		if ((n >> level & 1) != 0) {
			session.send(new HintResponse(req.getSerial(), MessageConst.VIP_GIFT_BOUGHT));
			return;
		}
		if (goods.getPrice() > 0 && !player.costStone(goods.getPrice(), Cause.VIP_BUY)) {
			session.send(new HintResponse(req.getSerial(), MessageConst.STONE_NOT_ENOUTH));
			return;
		}
		player.getBag().addItemWithoutException(goods.getId(), goods.getCount(), Cause.VIP_BUY);
		n |= 1 << level;
		player.poolSet(PlayerPool.PROPERTY_VIP_BUY_MARK, n);
		session.send(new Response(req.getSerial()));
		LOG.info("[VIPBUY]ID[{}]VIP[{}]REQ[{}]", player.getId(), player.getVipLvl(), level);
	}
	
}
